package com.hejia.alauda.service;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.UUID;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.hejia.alauda.entity.HejiaRedPacket;
import com.hejia.alauda.entity.HejiaRedPacketReceive;
import com.hejia.alauda.entity.User;
import com.hejia.alauda.entity.example.HejiaRedPacketExample;
import com.hejia.alauda.entity.example.HejiaRedPacketReceiveExample;
import com.hejia.alauda.persistence.mybatis.HejiaRedPacketMapper;
import com.hejia.alauda.persistence.mybatis.HejiaRedPacketReceiveMapper;
import com.hejia.alauda.utils.HongBaoAlgorithm;
import com.hejia.alauda.utils.Pager;

@Service
public class HejiaRedPacketServiceImpl implements HejiaRedPacketService {

	@Resource
	private HejiaRedPacketMapper hejiaRedPacketMapper;
	
	@Resource
	private HejiaRedPacketReceiveMapper hejiaRedPacketReceiveMapper;
	
	@Resource
	private BonusService bonusService;
	
	@Override
	public Pager<HejiaRedPacket> findHejiaRedPackets(Pager<HejiaRedPacket> pager, Date startTime, Date endTime) {
		
		HejiaRedPacketExample example = new HejiaRedPacketExample();
		if (startTime != null) {
			example.appendCriterion("receiveStartTime >", startTime);
		}
		if (endTime != null) {
			example.appendCriterion("receiveStartTime <", endTime);
		}
		example.setOrderByClause("id desc");
		
		pager.setList(hejiaRedPacketMapper.selectByExample(example, pager));
		pager.setTotalCount(hejiaRedPacketMapper.countByExample(example));
		
		return pager;
	}

	@Override
	public HejiaRedPacket addHejiaRedPacket(HejiaRedPacket hejiaRedPacket) {
		
		Integer totalAmount = hejiaRedPacket.getTotalAmount();
		Integer number = hejiaRedPacket.getNumber();
		Integer minAmount = hejiaRedPacket.getMinAmount();
		Integer maxAmount = hejiaRedPacket.getMaxAmount();
		Integer average = totalAmount / number;
		
		if (minAmount >= average) {
			throw new RuntimeException("最小金额必须小于红包平均金额");
		}
		if (maxAmount <= average) {
			throw new RuntimeException("最大金额必须小大红包平均金额");
		}
		
		long[] amounts = HongBaoAlgorithm.generate(
				totalAmount, 
				number, 
				maxAmount,
				minAmount);
		
		long actualTotalAmount = 0;
		for(int i = 0; i < number; i++) {
			actualTotalAmount += amounts[i];
		}
		
		if (amounts.length != number) {
			throw new RuntimeException("生成红包个数错误");
		}
		if (actualTotalAmount != totalAmount) {
			throw new RuntimeException("生成红包总金额错误");
		}
		
		hejiaRedPacket.setCreateDate(new Date());
		hejiaRedPacket.setModifyDate(new Date());
		hejiaRedPacket.setExternalId(UUID.randomUUID().toString());
		hejiaRedPacketMapper.insert(hejiaRedPacket);
		for(int i = 0; i < number; i++) {
			addHejiaRedPacketReceive(hejiaRedPacket, amounts[i]);
		}
		return hejiaRedPacket;
	}

	/**
	 * 添加红包领取
	 * @param hejiaRedPacket
	 * @param amount
	 */
	private void addHejiaRedPacketReceive(HejiaRedPacket hejiaRedPacket, long amount) {
		HejiaRedPacketReceive reveive = new HejiaRedPacketReceive();
		reveive.setCreateDate(new Date());
		reveive.setModifyDate(new Date());
		reveive.setHejiaRedPacket(hejiaRedPacket);
		reveive.setAmount(new Long(amount).intValue());
		hejiaRedPacketReceiveMapper.insert(reveive);
	}

	@Transactional(rollbackFor = Exception.class)
	@Override
	public void deleteHejiaRedPacket(Long id) {
		
		HejiaRedPacket hejiaRedPacket = hejiaRedPacketMapper.selectByPrimaryKey(id);
		hejiaRedPacketMapper.deleteByPrimaryKey(hejiaRedPacket);
		
		HejiaRedPacketReceiveExample example = new HejiaRedPacketReceiveExample();
		example.appendCriterion("hejiaRedPacket_id =", id);
		hejiaRedPacketReceiveMapper.deleteByHejiaRedPacketId(id);
	}

	@Override
	public HejiaRedPacket findhejiaRedPacketByExternalId(String externalId) {
		HejiaRedPacketExample example = new HejiaRedPacketExample();
		example.appendCriterion("externalId =", externalId);
		
		return hejiaRedPacketMapper.selectOneByExample(example);
	}

	@Override
	@Transactional
	public synchronized HejiaRedPacketReceive grapHejiaRedPacketByExternalId(User user, String externalId) {
		
		// 检查用户是否已领取红包
		if (countReceivedRedPacket(user, externalId) > 0) {
			throw new RuntimeException("一个用户，只能领取一个红包");
		}
		
		HejiaRedPacketExample hejiaRedPacketExample = new HejiaRedPacketExample();
		hejiaRedPacketExample.appendCriterion("externalId =", externalId);
		HejiaRedPacket hejiaRedPacket = hejiaRedPacketMapper.selectOneByExample(hejiaRedPacketExample);
		Date now = new Date();
		if (hejiaRedPacket.getReceiveStartTime().after(now)) {
			throw new RuntimeException("领取红包未开始，请耐心等待");
		}
		if (hejiaRedPacket.getReceiveEndTime().before(now)) {
			throw new RuntimeException("领取红包已经结束，请下次再来");
		}
		
		HejiaRedPacketReceiveExample hejiaRedPacketReceiveExample = new HejiaRedPacketReceiveExample();
		hejiaRedPacketReceiveExample.appendCriterion("hejiaRedPacket_id =", hejiaRedPacket.getId());
		hejiaRedPacketReceiveExample.appendCriterion("user_id is null");
		
		Pager<HejiaRedPacketReceive> pager = new Pager<>();
		pager.setPageSize(1);
		List<HejiaRedPacketReceive> hejiaRedPacketReceives = 
				hejiaRedPacketReceiveMapper.selectByExample(hejiaRedPacketReceiveExample, pager);
		if (hejiaRedPacketReceives.size() > 0) {
			HejiaRedPacketReceive hejiaRedPacketReceive = hejiaRedPacketReceives.get(0);
			hejiaRedPacketReceive.setUser(user);
			hejiaRedPacketReceive.setReceiveTime(now);
			hejiaRedPacketReceiveMapper.updateByPrimaryKey(hejiaRedPacketReceive);
			bonusService.addBonusRecordByRedpacket(user, "HEJIA_RED_PACKET", BigDecimal.valueOf(hejiaRedPacketReceive.getAmount()));
			return hejiaRedPacketReceive;
		}
		return null;
	}

	@Override
	public int countReceivedRedPacket(User user, String externalId) {
		return hejiaRedPacketReceiveMapper.countReceivedRedPacket(user.getId(), externalId);
	}

	@Override
	public List<HejiaRedPacketReceive> findHejiaRedPacketGrapInfoByRedPacketId(Long redPacketId) {
		HejiaRedPacketReceiveExample hejiaRedPacketReceiveExample = new HejiaRedPacketReceiveExample();
		hejiaRedPacketReceiveExample.appendCriterion("hejiaRedPacket_id =", redPacketId);
		hejiaRedPacketReceiveExample.appendCriterion("user_id is not null");
		hejiaRedPacketReceiveExample.setOrderByClause("receiveTime desc");
		return hejiaRedPacketReceiveMapper.selectByExample(hejiaRedPacketReceiveExample, null);
	}

}
